﻿Imports System.IO
Imports System.Text
Imports System.Text.RegularExpressions
Imports System.Security.Cryptography
Imports System.Collections.ObjectModel
Imports System.Management.Automation.Runspaces
Imports Microsoft.PowerShell


Module Commun
    Public BasicRights() As Integer = {278, 65536, 131209, 131241, 197055, 2032127}
    Public CaptureMacro As Boolean = True

    Friend Function GetDefaultCoul(ByVal Courante As String) As String
        'Construire une collection de couleurs de fond disponibles
        Dim oList As String() = {"#FFFF00", "#FF0000", "#00FF00", "#00FFFF", "#0080C0", "#C0C0C0", "#808080", "#FF00FF", "#8080FF", "#FF8040", "#78BCBC", "#B9B900", "#BB7777", "#6FFF6F", "#FFFFFF"}
        Dim oColCoul As New System.Collections.Specialized.StringCollection
        Dim noCoul As Integer = 0
        For Each sCoul As String In oList
            oColCoul.Add(sCoul)
        Next
        'Retirer les couleurs déjà prises par des marqueurs
        Dim oMarqueur As ClassMarqueur
        For Each oItem As ListViewItem In Form1.ListViewMarqueurs.Items
            oMarqueur = oItem.Tag
            If oColCoul.Contains(oMarqueur.CoulFondPrimaire) Then oColCoul.Remove(oMarqueur.CoulFondPrimaire)
        Next
        'Si il n'y a plus de couleurs libres, on a pas le choix de piger dans la liste complete
        If oColCoul.Count = 0 Then
            For Each sCoul As String In oList
                oColCoul.Add(sCoul)
            Next
            'Dans ce cas, on ne veut pas toujours utiliser la première car on veut répartir également
            If Courante = "" Then Courante = oColCoul.Item(Form1.ListViewMarqueurs.Items.Count + 1 Mod oColCoul.Count)
        End If
        If Courante = "" Then Courante = oColCoul.Item(0)
        'On prend la couleur qui suit la courante
        noCoul = oColCoul.IndexOf(Courante) + 1
        If noCoul >= oColCoul.Count Then noCoul = 0
        Return oColCoul.Item(noCoul)
    End Function

    Friend Function GetCoulInv(ByVal CoulPrim As String) As String
        Dim oCoul As Color = System.Drawing.ColorTranslator.FromHtml(CoulPrim)
        Dim iCoul As Integer = ColorTranslator.ToWin32(oCoul)
        iCoul = Not (iCoul)
        oCoul = ColorTranslator.FromWin32(iCoul)
        Return System.Drawing.ColorTranslator.ToHtml(oCoul)
    End Function

    Friend Function GetCoulComp(ByVal CoulPrim As String) As String
        Dim oCoul As Color = System.Drawing.ColorTranslator.FromHtml(CoulPrim)
        oCoul = ControlPaint.LightLight(oCoul)
        Return System.Drawing.ColorTranslator.ToHtml(oCoul)
    End Function


#Region "Fichiers XML"

    Public Sub SaveXML(ByRef Objet As Object, ByVal FichierXML As String)
        'Procédure qui serialise un objet en mémoire dans le fichier XML spécifié
        Try
            Dim oWriter As New System.Xml.XmlTextWriter(FichierXML, System.Text.Encoding.Default)
            Dim oSerializer As New System.Xml.Serialization.XmlSerializer(Objet.GetType)
            oSerializer.Serialize(oWriter, Objet)
            oWriter.Close()
        Catch Ex As Exception
            MsgBox("Enregistrement impossible :" & Ex.Message, MsgBoxStyle.Exclamation)
        End Try
    End Sub

    Public Function LoadXML(ByRef Objet As Object, ByVal FichierXML As String) As Boolean
        'Fonction qui désérialise un objet à partir du fichier XML spécifié.
        'Retourne vrai si réussi, Faux sinon.
        If My.Computer.FileSystem.FileExists(FichierXML) Then
            Dim oReader As New System.Xml.XmlTextReader(FichierXML)
            Dim oSerializer As New System.Xml.Serialization.XmlSerializer(Objet.GetType())
            Try
                Objet = oSerializer.Deserialize(oReader)
                oReader.Close()
                Return True
            Catch ex As Exception
                MsgBox("Erreur à la lecture du fichier " & FichierXML & vbCrLf & ex.Message, MsgBoxStyle.Exclamation)
                Return False
            End Try
        Else
            Return Nothing
        End If
    End Function

#End Region

#Region "Manipulations de chaînes"

    Public Function TestRegex(ByVal sChaine As String, ByVal sRegex As String) As Boolean
        Try
            Dim oMatch As System.Text.RegularExpressions.Match = System.Text.RegularExpressions.Regex.Match(sChaine, sRegex, RegexOptions.IgnoreCase Or RegexOptions.Multiline)
            Return (oMatch.Value = sChaine)
        Catch ex As Exception
            Return False
        End Try
    End Function

    Public Function CompterFichiers(ByVal sRef As String, ByVal sRegex As String, ByVal sChaineRecherchee As String, ByVal sRapport As String, ByVal sChemin As String, ByVal sMasque As String, ByVal bRecurse As Boolean) As String
         'Cette première version retourne le nombre de fichiers trouvés pour chaque chaine.
        Dim sSortie As String = vbCrLf
        'Construire les chaines de recherche et de rapport
        Dim colRecherche As New ClassColRechercheIndirecteResult
        Dim iFichiersMasques As Integer = 0
        If sRegex <> "" Then
            For Each oMatch As System.Text.RegularExpressions.Match In System.Text.RegularExpressions.Regex.Matches(sRef, sRegex, RegexOptions.IgnoreCase Or RegexOptions.Multiline)
                Dim oResult As New ClassRechercheIndirecteResult(sChaineRecherchee, sRapport)
                For i = 0 To oMatch.Groups.Count - 1
                    oResult.sRecherchee = oResult.sRecherchee.Replace("$" & i, oMatch.Groups(i).Value.ToUpper)
                    oResult.sRapport = oResult.sRapport.Replace("$" & i, oMatch.Groups(i).Value)
                Next
                If Not colRecherche.Contains(oResult.sRecherchee) Then colRecherche.add(oResult)
            Next
        Else
            Dim oResult As New ClassRechercheIndirecteResult(sChaineRecherchee, sRapport)
            colRecherche.add(oResult)
        End If
        'Fouiller les fichiers
        If My.Computer.FileSystem.DirectoryExists(sChemin) Then
            Dim oDirInfo As DirectoryInfo = My.Computer.FileSystem.GetDirectoryInfo(sChemin)
            If sMasque = "" Then sMasque = "*.*"
            Dim oOptions As System.IO.SearchOption = SearchOption.TopDirectoryOnly
            If bRecurse Then oOptions = SearchOption.AllDirectories
            Dim ColInfo As FileInfo() = oDirInfo.GetFiles(sMasque, oOptions)
            FormCompteFichiers.ProgressBar1.Maximum = ColInfo.Count
            FormCompteFichiers.ProgressBar1.Value = 0
            For Each oFileInfo As FileInfo In ColInfo
                iFichiersMasques += 1
                FormCompteFichiers.ProgressBar1.Value = iFichiersMasques
                My.Application.DoEvents()
                If sChaineRecherchee <> "" Then
                    'Faire la recherche
                    Dim oNewDoc As New ClassDocument(oFileInfo.FullName, True)
                    oNewDoc.Contenu = oNewDoc.Contenu.ToUpper
                    For Each oResult As ClassRechercheIndirecteResult In colRecherche
                        oResult.Check(oNewDoc.Contenu)
                    Next
                    oNewDoc = Nothing
                End If
            Next
            'Sortir les résultats
            If sChaineRecherchee <> "" Then
                For Each oResult As ClassRechercheIndirecteResult In colRecherche
                    If oResult.iFicTrouves > 0 Then sSortie = Commun.AppendString(sSortie, oResult.GetRapport(), vbCrLf)
                Next
            Else
                sSortie = Commun.AppendString(sSortie, System.Text.RegularExpressions.Regex.Replace(sRapport, "\$NB", iFichiersMasques.ToString, RegexOptions.IgnoreCase), vbCrLf)
                'sSortie = Commun.AppendString(sSortie, sRapport.Replace("$NB", iFichiersMasques.ToString), vbCrLf)
            End If
        End If
        If sSortie = "" Then sSortie = "Aucun"
        Return sSortie
    End Function

    Public Function RemplacerTexte(ByVal Chaine As String, ByVal sCherche As String, ByVal sRemplace As String, ByVal Multiple As Boolean) As String
        If Multiple Then
            Dim tCherche() As String = sCherche.Split(",")
            Dim tRemplace() As String = sRemplace.Split(",")
            If tCherche.Count = tRemplace.Count Then
                For i = tCherche.GetLowerBound(0) To tCherche.GetUpperBound(0)
                    Chaine = Chaine.Replace(tCherche(i), tRemplace(i))
                Next
                Return Chaine
            Else
                Return Chaine
            End If
        Else
            Return Chaine.Replace(sCherche, sRemplace)
        End If
    End Function

    Public Function Lookup(ByVal sModif As String, ByVal sFindRegEx As String, ByVal sReplace As String, ByVal sLookupRegEx As String, ByVal sRefFile As String, ByVal sIntrouvable As String)
        If My.Computer.FileSystem.FileExists(sRefFile) Then
            Return LookupRef(sModif, sFindRegEx, sReplace, sLookupRegEx, My.Computer.FileSystem.ReadAllText(sRefFile), sIntrouvable)
        Else
            Return sModif
        End If
    End Function

    Public Function LookupRef(ByVal sModif As String, ByVal sFindRegEx As String, ByVal sReplace As String, ByVal sLookupRegEx As String, ByVal sRef As String, ByVal sIntrouvable As String)
        'Fonction de remplacement d'expression régulière avec lookup dans un chaine de référence.
        'sModif      =  Chaine à modifier
        'sFindRegex  =  Expression régulière de recherche à utiliser pour le remplacement
        'sReplace    =  Chaine de remplacement avec lookup.
        '              $x = remplace par le submatch x défini par sFindRegex
        '              $$x = remplace par le submatch x trouvé par le lookup
        'sLookupRegx = Expression de recherche dans la chaine de référence.
        '              Les $x dans l'expression sont remplacé par les submatch correspondants de sFindRegex
        'sRef        = Chaine de référence pour la recherche lookup
        '
        'Exemple: Lookup("Region=SS,Region=BL", "Region=(\w\w)", "Region=$1($$1)", "$1=(\w+)", "SS=Bourdages,BL=Bleury") -> "Region=SS(Bourdages),Region=BL(Bleury)"
        '
        For Each oMatch As System.Text.RegularExpressions.Match In System.Text.RegularExpressions.Regex.Matches(sModif, sFindRegEx, RegexOptions.IgnoreCase)
            'On construit la requete lookup en remplacant les $x dans sLookupRegEx
            Dim sLookup As String = sLookupRegEx
            For i = 0 To oMatch.Groups.Count - 1
                sLookup = sLookup.Replace("$" & i, oMatch.Groups(i).Value)
            Next 'i
            'Exécuter la requete lookup
            Dim oLookupMatch As System.Text.RegularExpressions.Match = System.Text.RegularExpressions.Regex.Match(sRef, sLookup, RegexOptions.IgnoreCase)
            'Appliquer les résultats du lookup dans sReplace
            Dim sReplaceNew As String = ""
            If oLookupMatch.Length > 0 Then
                sReplaceNew = sReplace
                For i = 0 To oLookupMatch.Groups.Count - 1
                    sReplaceNew = sReplaceNew.Replace("$$" & i, oLookupMatch.Groups(i).Value)
                Next
            Else
                sReplaceNew = sIntrouvable
                For i = 0 To 9
                    sReplaceNew = sReplaceNew.Replace("$" & i, oMatch.Groups(i).Value)
                Next
            End If
            'Appliquer les résultats de la recherche initiale dans sReplace
            For i = 0 To oMatch.Groups.Count - 1
                sReplaceNew = sReplaceNew.Replace("$" & i, oMatch.Groups(i).Value)
            Next 'i
            'Exécuter le remplacement 
            sModif = sModif.Replace(oMatch.Value, sReplaceNew)
        Next 'oMatch
        Return sModif
    End Function

    Public Function SeparerLignes(ByVal chaine As String, ByVal Sep As String) As String
        Return Join(System.Text.RegularExpressions.Regex.Split(chaine, Sep, RegexOptions.IgnoreCase Or RegexOptions.Multiline), vbCrLf)
    End Function

    Public Function FusionnerLignes(ByVal Chaine As String) As String
        Dim Lignes() As String = Split(Chaine.Replace(vbCrLf, vbLf), vbLf)
        Chaine = ""
        For Each sLigne As String In Lignes
            sLigne = sLigne.Trim()
            If sLigne <> "" Then
                If Chaine <> "" Then Chaine &= " "
                Chaine &= sLigne
            End If
        Next
        Return Chaine
    End Function

    Public Function Pivoter(ByVal chaine As String) As String
        chaine = chaine.Replace(vbCrLf, vbLf)
        Dim Lignes() As String = Split(chaine, vbLf)
        chaine = ""
        For Each L As String In Lignes
            L = System.Text.RegularExpressions.Regex.Replace(L, "(.+)(\s*=\s*)(.+)", "$3$2$1")
            If chaine <> "" Then chaine &= vbCrLf
            chaine &= L
        Next
        Return chaine
    End Function

    Public Function TrimAvant(ByVal Chaine As String) As String
        Chaine = Chaine.Replace(vbCrLf, vbLf)
        Dim Lignes() As String = Split(Chaine, vbLf)
        Chaine = ""
        For Each L As String In Lignes
            L = L.TrimStart
            If Chaine <> "" Then Chaine &= vbCrLf
            Chaine &= L
        Next
        Return Chaine
    End Function

    Public Function TrimApres(ByVal Chaine As String) As String
        Chaine = Chaine.Replace(vbCrLf, vbLf)
        Dim Lignes() As String = Split(Chaine, vbLf)
        Chaine = ""
        For Each L As String In Lignes
            L = L.TrimEnd
            If Chaine <> "" Then Chaine &= vbCrLf
            Chaine &= L
        Next
        Return Chaine
    End Function

    Public Function TrimLignesBlanches(ByVal Chaine As String) As String
        Chaine = vbCrLf & Chaine & vbCrLf 'On s'assure de ne pas avoir un tableau vide.
        Dim Lignes() As String = Split(Chaine, vbCrLf)
        If Lignes.Count > 0 Then
            Dim iStart As Integer = Lignes.GetLowerBound(0)
            Do While (iStart < Lignes.GetUpperBound(0)) And (Lignes(iStart) = "")
                iStart += 1
            Loop
            Dim iStop As Integer = Lignes.GetUpperBound(0)
            Do While (iStop > iStart) And (Lignes(iStop) = "")
                iStop -= 1
            Loop
            Chaine = ""
            For i As Integer = iStart To iStop
                Chaine = Commun.AppendString(Chaine, Lignes(i), vbCrLf)
            Next
        End If
        Return Chaine
    End Function

    Public Function TrimTout(ByVal Chaine As String) As String
        Chaine = Chaine.Replace(vbCrLf, vbLf)
        Dim Lignes() As String = Split(Chaine, vbLf)
        Chaine = ""
        For Each L As String In Lignes
            L = L.Trim
            If Chaine <> "" Then Chaine &= vbCrLf
            Chaine &= L
        Next
        Return Chaine
    End Function

    Public Function RemplaceCar(ByVal Chaine As String, ByVal TableRemp As String, ByVal TablePar As String) As String
        Dim Result As String = ""
        If (Chaine.Length > 0) And (TablePar.Length = TableRemp.Length) Then
            Dim Car As Char
            'On boucle sur tous les caractères car on ne veut pas remplacer deux fois le même
            'Ce qui arriverait en utilisant Chaine.Replace pour tous les cars de TableRemp...
            For cIndex = 0 To Chaine.Length - 1
                Car = Chaine.Chars(cIndex)
                For iIndex = 0 To TableRemp.Length - 1
                    If Car = TableRemp(iIndex) Then
                        Car = TablePar(iIndex)
                        Exit For
                    End If
                Next
                Result &= Car
            Next
            Return Result
        Else
            Return Chaine
        End If
    End Function

    Public Function MettreEnColonnes(ByVal Chaine As String, ByVal Sep As String)
        Dim Largeurs(1) As Integer
        Chaine = Replace(Chaine, vbCrLf, vbLf)
        Dim Lignes() As String = Split(Chaine, vbLf)
        'Phase 1: On calcule les largeurs
        For Each sLigne As String In Lignes
            sLigne = Regex.Replace(sLigne, Sep, Chr(10))
            Dim noColonne As Integer = 0
            For Each sMot As String In Split(sLigne, Chr(10))
                noColonne += 1
                If noColonne > Largeurs.GetUpperBound(0) Then
                    ReDim Preserve Largeurs(noColonne)
                    Largeurs(noColonne) = sMot.Length
                End If
                If sMot.Length > Largeurs(noColonne) Then Largeurs(noColonne) = sMot.Length
            Next
        Next
        'Phase 2: On ajuste les largeurs
        Chaine = ""
        For Each sLigne As String In Lignes
            If Chaine <> "" Then Chaine &= vbCrLf
            Dim noColonne As Integer = 0
            sLigne = Regex.Replace(sLigne, Sep, Chr(10))
            For Each sMot As String In Split(sLigne, Chr(10))
                noColonne += 1
                Chaine &= sMot.PadRight(Largeurs(noColonne) + 1, " ")
            Next
        Next
        Return Chaine
    End Function

    Public Function Aligner(ByVal Chaine As String, ByVal Sep As String)
        Dim Largeur As Integer = 0
        Dim oMatch As Match
        Chaine = Replace(Chaine, vbCrLf, vbLf)
        Dim Lignes() As String = Split(Chaine, vbLf)
        'Phase 1: On calcule les largeurs
        For Each sLigne As String In Lignes
            'Elimine les blancs en avant
            sLigne = Regex.Replace(sLigne, "\s*(" & Sep & ")\s*", "$1")
            oMatch = Regex.Match(sLigne, Sep)
            If oMatch.Success Then
                If oMatch.Index > Largeur Then Largeur = oMatch.Index
            End If
        Next
        Largeur += 1 'On veut au moins un blanc à gauche
        'Phase 2: On aligne 
        Chaine = ""
        For Each sLigne As String In Lignes
            sLigne = Regex.Replace(sLigne, "\s*(" & Sep & ")\s*", "$1")
            oMatch = Regex.Match(sLigne, Sep)
            If oMatch.Success Then
                sLigne = Regex.Replace(sLigne, "(" & Sep & ")", Space(Largeur - oMatch.Index) & "$1" & " ")
            End If
            If Chaine <> "" Then Chaine &= vbCrLf
            Chaine &= sLigne
        Next
        Return Chaine
    End Function

    Function Encadrer(ByVal Chaine As String, ByVal Car As Char) As String
        Chaine = Replace(Chaine, vbCrLf, vbLf)
        Dim Lignes() As String = Split(Chaine, vbLf)
        Dim Largeur As Integer = 0
        For Each sLigne As String In Lignes
            If sLigne.Length > Largeur Then Largeur = sLigne.Length()
        Next
        Return vbCrLf & StrDup(Largeur, Car) & vbCrLf & Chaine & vbCrLf & StrDup(Largeur, Car)
    End Function

    Public Function Indent(ByVal Chaine As String, ByVal NbColonnes As Integer) As String
        If NbColonnes > 0 Then
            Return Regex.Replace(Chaine, "^(.*)$", Space(NbColonnes) & "$1", RegexOptions.IgnoreCase Or RegexOptions.Multiline)
        Else
            Return Regex.Replace(Chaine, "^(" & Space(Math.Abs(NbColonnes)) & ")(.*)$", "$2", RegexOptions.IgnoreCase Or RegexOptions.Multiline)
        End If
    End Function

    Public Function Reformater(ByVal Chaine As String, ByVal Largeur As Integer) As String
        Dim sChaines() As String = Split(Regex.Replace(Chaine, "\r\n|\n|\r", " "), " ")
        Dim sLigne As String = ""
        Dim sResult As String = ""
        For Each sChaine As String In sChaines
            If sLigne > "" Then sLigne &= " "
            If sLigne.Length + sChaine.Length <= Largeur Then
                sLigne &= sChaine
            Else
                sResult &= RTrim(sLigne) & vbCrLf
                sLigne = ""
                While sChaine.Length > Largeur
                    sResult &= sChaine.Substring(1, Largeur)
                    sChaine = sChaine.Substring(Largeur, sChaine.Length - Largeur)
                End While
                sLigne = sChaine
            End If
        Next
        'If sResult <> "" Then sResult &= vbCrLf
        Return sResult & sLigne
    End Function

    Public Function Trier(ByVal Chaine As String, ByVal Sep As String) As String
        Chaine = Replace(Chaine, vbCrLf, vbLf)
        If Sep = vbCrLf Then Sep = vbLf
        Dim sLignes() As String = Split(Chaine, vbLf)
        If Sep = vbLf Then
            'On tri par ligne
            Array.Sort(sLignes)
            Return Join(sLignes, Sep)
        Else
            'On tri le contenu de chaque ligne
            Dim sResult As String = ""
            For Each sLigne As String In sLignes
                Dim sTableau() As String = System.Text.RegularExpressions.Regex.Split(sLigne, Sep)
                Array.Sort(sTableau)
                'Reconstituer la ligne avec les séparateurs
                Dim oColMatch As System.Text.RegularExpressions.MatchCollection = System.Text.RegularExpressions.Regex.Matches(sLigne, Sep, RegexOptions.IgnoreCase)
                sLigne = ""
                For i = 0 To sTableau.Length - 1
                    sLigne &= sTableau(i)
                    If oColMatch.Count >= i + 1 Then sLigne &= oColMatch.Item(i).Value
                Next
                If sResult <> "" Then sResult &= vbCrLf
                sResult &= sLigne
            Next
            Return sResult
        End If
    End Function

    Public Function cStringToUnicode(ByVal Valeur As String) As String
        'Retourne la chaîne avec les caractères > 126 convertis au format \uxxxx
        'ce qui correspond aux caractères d'échappement java.
        Dim Chaine As String = ""
        Dim iVal As Integer
        For Each cCar As Char In Valeur
            iVal = Asc(cCar)
            If iVal > 126 Then
                Chaine &= "\u00" & iVal.ToString("X")
            Else
                Chaine &= cCar
            End If
        Next
        Return Chaine
    End Function

    Public Function Justifier(ByVal Chaine As String) As String
        'On retire les espaces surnuméraires
        Dim Result As String = ""
        Chaine = Regex.Replace(Chaine, "  +", " ")
        'Etape 1: On calcule la largeur maximale
        Dim iLargeur As Integer = 0
        For Each sLigne As String In Chaine.Split(vbLf)
            sLigne = RTrim(sLigne)
            If sLigne.Length > iLargeur Then iLargeur = sLigne.Length
        Next
        'Etape 2: On insère les espaces manquants dans toutes les lignes sauf la dernière
        Dim Lignes() As String = Chaine.Split(vbLf)
        If Lignes.GetUpperBound(0) > 0 Then
            For NoLigne = 0 To Lignes.GetUpperBound(0) - 1
                Dim sLigne As String = RTrim(Lignes(NoLigne))
                Dim iManquants As Integer = iLargeur - sLigne.Length
                If iManquants > 0 Then
                    Dim Mots() As String = sLigne.Split(" ")
                    Dim iDiv As Integer = Mots.GetUpperBound(0)
                    If iDiv > 0 Then
                        Dim iCommun As Integer = Math.Floor(iManquants / iDiv)
                        If iCommun > 0 Then
                            For i As Integer = 0 To Mots.GetUpperBound(0) - 1
                                Mots(i) &= Space(iCommun)
                            Next
                        End If
                        Dim iReste As Integer = iManquants Mod iDiv
                        If iReste > 0 Then
                            For i As Integer = 1 To iReste
                                Mots(i) &= " "
                            Next
                        End If
                    End If
                    sLigne = ""
                    For Each Mot As String In Mots
                        If sLigne <> "" Then sLigne &= " "
                        sLigne &= Mot
                    Next
                End If
                If Result <> "" Then Result &= vbLf
                Result &= sLigne
            Next
            'Dernière ligne
            If Result <> "" Then Result &= vbLf
            Result &= Lignes(Lignes.GetUpperBound(0))
        End If
        Return Result
    End Function

    Public Function cUnicodeToString(ByVal Valeur As String) As String
        For Each oMatch As Match In Regex.Matches(Valeur, "\\u([0-9a-f]{4})", RegexOptions.Multiline Or RegexOptions.IgnoreCase)
            Dim sHexa As String = oMatch.Groups(1).Value
            Dim iValeur As Long = CInt("&h" & oMatch.Groups(1).Value)
            Valeur = Valeur.Replace(oMatch.Value, Chr(iValeur))
        Next
        Return Valeur
    End Function

    Public Function DomainToLDAP(ByVal Adresse As String) As String
        DomainToLDAP = ""
        For Each sPartie As String In Split(Adresse, ".")
            If DomainToLDAP <> "" Then DomainToLDAP &= ","
            DomainToLDAP &= "DC=" & sPartie
        Next
        DomainToLDAP = "LDAP://" & DomainToLDAP
    End Function

    Public Function LDAPToDomain(ByVal LDAP As String) As String
        LDAPToDomain = Regex.Replace(LDAP, "LDAP://", "", RegexOptions.IgnoreCase)
        LDAPToDomain = Regex.Replace(LDAPToDomain, "DC=", "", RegexOptions.IgnoreCase)
        LDAPToDomain = Regex.Replace(LDAPToDomain, ",", ".", RegexOptions.IgnoreCase)
    End Function

    Public Function LigneListe(ByVal Chaine As String) As String
        Return Chaine.Replace(vbLf, ",")
    End Function

    Public Function ListeLigne(ByVal Chaine As String) As String
        Return Chaine.Replace(",", vbLf)
    End Function

    Public Function ConvertToAdminPath(ByVal sComputerName As String, ByVal sChemin As String) As String
        If sComputerName <> My.Computer.Name Then
            Return "\\" & sComputerName & "\" & sChemin.Replace(":", "$")
        Else
            Return sChemin
        End If
    End Function

    Public Function ExtrairePremiersMots(ByVal Chaine As String, ByVal NbMots As Integer) As String
        Dim sResult As String = ""
        Dim iCompteur As Integer = 0
        For Each oMatch As Match In Regex.Matches(Chaine, "\w+", RegexOptions.IgnoreCase Or RegexOptions.Multiline)
            iCompteur += 1
            If sResult <> "" Then sResult &= " "
            sResult &= oMatch.Value
            If iCompteur = NbMots Then Exit For
        Next
        Return sResult
    End Function

    Public Function SupprimerLignesDoubles(ByVal Chaine As String) As String
        Dim oCol As New System.Collections.Specialized.StringCollection
        Chaine = Replace(Chaine, vbCrLf, vbLf)
        Dim sResult As String = ""
        For Each sLigne As String In Split(Chaine, vbLf)
            If Not oCol.Contains(sLigne.ToUpper) Then
                oCol.Add(sLigne.ToUpper)
                If sResult <> "" Then sResult &= vbCrLf
                sResult &= sLigne
            End If
        Next
        Return sResult
    End Function

    Public Function SupprimerLignesVides(ByVal Chaine As String) As String
        'CODE ORIGINAL
        Chaine = Replace(Chaine, vbCrLf, vbLf)
        Dim sResult As String = ""
        For Each sLigne As String In Split(Chaine, vbLf)
            If Not sLigne.Trim() = "" Then
                If sResult <> "" Then sResult &= vbCrLf
                sResult &= sLigne
            End If
        Next
        Return sResult
    End Function

    Public Function Numeroter(ByVal Chaine As String) As String
        Dim sResult As String = ""
        Dim Compteurs(64) As Integer
        Dim Indent(64) As Integer
        Dim LastIndent As Integer
        Dim Niveau As Integer = 1
        Compteurs(1) = 0
        Indent(1) = 0
        LastIndent = 0
        Dim oRegEx As New System.Text.RegularExpressions.Regex("^( *)([\d\.]+) ", RegexOptions.IgnoreCase)
        For Each sLigne As String In Split(Chaine, vbLf)
            'On ne numérote pas les lignes vide
            If sLigne.Trim() <> "" Then
                'Effacer la numérotation existante
                sLigne = oRegEx.Replace(sLigne, "$1")
                'On renumérote juste si ce ne l'était pas déjà
                'On trouve le niveau d'indentation
                Dim CurIndent As Integer = LeadingSpaces(sLigne)
                If CurIndent > LastIndent Then
                    'On est plus indenté que la ligne précédente, donc on monte d'un niveau de numérotation
                    If Niveau <= 64 Then Niveau += 1
                    Compteurs(Niveau) = 0
                    Indent(Niveau) = CurIndent
                    LastIndent = CurIndent
                Else
                    'On recule de niveau d'indentation si besoin
                    Do While (Niveau > 1) And (CurIndent < LastIndent)
                        Niveau -= 1
                        LastIndent = Indent(Niveau)
                    Loop
                End If
                'On compte un élément de plus au niveau courant
                Compteurs(Niveau) += 1
                'On génère la numérotation sous la forme 1.2.3
                Dim Numero As String = ""
                For i = 1 To Niveau
                    If Numero <> "" Then Numero &= "."
                    Numero &= Compteurs(i)
                Next
                'On ajoute le tout à la ligne en respectant l'indentation
                sLigne = Space(CurIndent) & Numero & " " & sLigne.Trim()
            End If
            If sResult <> "" Then sResult &= vbCrLf
            sResult &= sLigne
        Next
        Return sResult
    End Function

    Public Function DeNumeroter(ByVal Chaine As String) As String
        Dim sResult As String = ""
        Dim oRegEx As New System.Text.RegularExpressions.Regex("^( *)([\d\.]+) ", RegexOptions.IgnoreCase)
        For Each sLigne As String In Split(Chaine, vbLf)
            sLigne = oRegEx.Replace(sLigne, "$1")
            If sResult <> "" Then sResult &= vbCrLf
            sResult &= sLigne
        Next
        Return sResult
    End Function

    Private Function LeadingSpaces(ByVal Chaine As String) As Integer
        LeadingSpaces = 0
        Do While Chaine.StartsWith(Space(LeadingSpaces + 1))
            LeadingSpaces += 1
        Loop
    End Function
#End Region

#Region "Securite"
    'Pour les fonctions de sécurités importées de ACLDIFF

    Public Function AppendString(ByVal Chaine As String, ByVal Ajout As String, ByVal Separateur As String) As String
        'Concatène Ajout à la fin de Chaine en utilisant un caractère séparateur
        If Ajout = "" Then
            Return Chaine
        Else
            If Chaine = "" Then
                Return Ajout
            Else
                Return Chaine & Separateur & Ajout
            End If
        End If
    End Function

    Public Function GetShortName(ByVal RightName As String) As String
        'Converti un nom long de droits en abbréviation en ne retenant que les
        'lettres en majuscules.
        Dim sShort As String = ""
        For Each sChar As Char In RightName
            If Char.IsUpper(sChar) Then sShort &= sChar
        Next
        Return sShort
    End Function

    Public Sub VBScriptHelp()
        Try
            Dim binWriter = New IO.BinaryWriter(IO.File.Create("VBSCriptHelp.chm"))
            binWriter.Write(My.Resources.Windows_Scripting_Host_5_6_New)
            binWriter.Close()
            Process.Start("VBSCriptHelp.chm")
            binWriter.Dispose()
        Catch Ex As Exception
            'On fait rien
        End Try
    End Sub

    Public Sub Guide()
        Try
            Dim binWriter = New IO.BinaryWriter(IO.File.Create("scpEdit_Guide.pdf"))
            binWriter.Write(My.Resources.scpEdit_Guide)
            binWriter.Close()
            Process.Start("scpEdit_Guide.pdf")
            binWriter.Dispose()
        Catch Ex As Exception
            'On fait rien
        End Try
    End Sub

#End Region

    Public Function ExpandRegex(ByVal sRegex As String) As String
        Dim Expanded As String = sRegex
        For Each oMatch As Match In Regex.Matches(sRegex, "%(.+?)%", RegexOptions.IgnoreCase)
            If Form1.ListViewMarqueurs.Items.ContainsKey(oMatch.Groups(1).Value) Then
                Expanded = Expanded.Replace(oMatch.Value, Form1.ListViewMarqueurs.Items(oMatch.Groups(1).Value).Tag.Masque)
            Else
                Expanded = Expanded.Replace(oMatch.Value, ".*?")
            End If
        Next
        Return Expanded
    End Function

    Public Sub AjouterHistoriqueMacro(ByVal Commande As String)
        'Ajouter une commande à l'historique d'exécution
        If Commun.CaptureMacro Then FormMacro.TextBoxHisto.AppendText(Commande & vbCrLf)
    End Sub

    Public Function RunShell(ByVal CommandText As String) As String
        'Exécuter la commande
        If CommandText <> "" Then
            CommandText = CommandText.Replace("%f", "%F")
            CommandText = CommandText.Replace("%F", Form1.DocumentCourant.Chemin)
            Dim oProcess As System.Diagnostics.Process
            Dim oStartInfo As New System.Diagnostics.ProcessStartInfo
            oStartInfo.StandardOutputEncoding = System.Text.Encoding.GetEncoding(850)
            oStartInfo.FileName = "cmd.exe"
            oStartInfo.Arguments = "/c " & CommandText
            oStartInfo.RedirectStandardOutput = True
            oStartInfo.UseShellExecute = False
            oStartInfo.WorkingDirectory = My.Computer.FileSystem.SpecialDirectories.Temp
            oStartInfo.WindowStyle = ProcessWindowStyle.Hidden
            Dim sSortie As String = ""
            oProcess = System.Diagnostics.Process.Start(oStartInfo)
            Do Until oProcess.HasExited
                sSortie &= oProcess.StandardOutput.ReadToEnd()
                System.Threading.Thread.Sleep(100)
                My.Application.DoEvents()
            Loop
            sSortie &= oProcess.StandardOutput.ReadToEnd()
            oProcess = Nothing
            Return sSortie
        Else
            Return ""
        End If
    End Function

    Public Function RunPowerShell(ByVal scriptText As String) As String
        If scriptText <> "" Then
            scriptText = scriptText.Replace("%F", Form1.DocumentCourant.Chemin)
            ' create Powershell runspace 
            Dim MyRunSpace As System.Management.Automation.Runspaces.Runspace = System.Management.Automation.Runspaces.RunspaceFactory.CreateRunspace()
            MyRunSpace.Open()
            ' create a pipeline and feed it the script text 
            Dim MyPipeline As System.Management.Automation.Runspaces.Pipeline = MyRunSpace.CreatePipeline()
            MyPipeline.Commands.AddScript(scriptText)
            ' add an extra command to transform the script output objects into nicely formatted strings 
            ' remove this line to get the actual objects that the script returns. For example, the script 
            ' "Get-Process" returns a collection of System.Diagnostics.Process instances. 
            MyPipeline.Commands.Add("Out-String")
            Dim sSortie As String = ""
            ' execute the script 
            Try
                Dim results As Collection(Of System.Management.Automation.PSObject) = MyPipeline.Invoke()
                ' convert the script result into a single string 
                Dim MyStringBuilder As New StringBuilder()
                For Each obj As System.Management.Automation.PSObject In results
                    MyStringBuilder.AppendLine(obj.ToString())
                Next
                ' return the results of the script that has now been converted to text 
                sSortie = MyStringBuilder.ToString()
            Catch ex As Exception
                sSortie = ex.Message
            End Try
            ' close the runspace 
            MyRunSpace.Close()
            Return sSortie
        Else
            Return ""
        End If
    End Function

    Public Function CompteMots(ByVal Chaine As String) As Integer
        Return System.Text.RegularExpressions.Regex.Matches(Chaine, "\b\S+\b").Count
    End Function
End Module
